using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

namespace CreamX
{
    public class Profile
    {
        Stopwatch Timer;

        private bool PropertyIsProfiling;
        private double PropertyTotalTime;
        private double PropertyMaxTime;
        private int PropertyName;
        private double PropertyCalls;
        public Profile(int Name)
        {
            PropertyName = Name;

            PropertyIsProfiling = false;
            PropertyTotalTime = 0f;
            PropertyMaxTime = 0f;
            PropertyCalls = 0;

            Timer = new Stopwatch();
        }

        public void StartProfiling()
        {
            Timer.Start();
            PropertyIsProfiling = true;
        }

        public void StopProfiling()
        {
            Timer.Stop();

            double __v = Timer.Elapsed.TotalSeconds;

            PropertyTotalTime += __v;

            if (PropertyMaxTime < __v)
                PropertyMaxTime = __v;

            PropertyCalls++;
            PropertyIsProfiling = false;
            Timer.Reset();
        }

        public double Calls
        {
            get { return (PropertyCalls); }
        }

        public double AverageTime
        {
            get { return (PropertyCalls > 0 ? PropertyTotalTime / PropertyCalls : 0); }
        }

        public bool IsProfiling
        {
            get { return (PropertyIsProfiling); }
        }

        public double MaxTime
        {
            get { return PropertyMaxTime; }
        }

        public int Name
        {
            get { return (PropertyName); }
        }

        public double TotalTime
        {
            get { return PropertyTotalTime; }
        }
    }

    public static class CreamXProfiler
    {
        public static bool ProfilingEnabled = true;

        static Dictionary<int, Profile> PropertyProfiles;

        static CreamXProfiler()
        {
            PropertyProfiles = new Dictionary<int, Profile>();
        }

        private static Profile GetProfileByName(int id)
        {
            if (PropertyProfiles.ContainsKey(id))
                return PropertyProfiles[id];
            else
                return null;
        }

        public static void StartProfiling(ProfilerName id)
        {
#if(PROFILE)
            if (ProfilingEnabled)
            {

                Profile Item = GetProfileByName((int)id);

                if (Item == null)
                {
                    Item = new Profile((int)id);
                    PropertyProfiles.Add((int)id, Item);
                }

                if (Item.IsProfiling)
                    throw new NotSupportedException(id + " is currently profiling, try stopping it first");

                Item.StartProfiling();
            }
#endif
        }

        public static void StopProfiling(ProfilerName id)
        {
#if(PROFILE)
            if (ProfilingEnabled)
            {
                Profile Item = GetProfileByName((int)id);

                if (Item == null)
                    throw new NotSupportedException("Profile doesn't exist");

                if (!Item.IsProfiling)
                    throw new NotSupportedException(id + " isn't currently profiling, try starting it first");

                Item.StopProfiling();
            }
#endif
        }

        public static Dictionary<int, Profile> Profiles
        {
            get { return (PropertyProfiles); }
        }
    }

    public enum ProfilerName:int
    {
        SetObjectsInLocalSpace,
        CheckType,
        CreamXUpdate,
        CreamXDraw,
        CreamXDrawTileBatch,
        CreamXDrawObjects,
        GameplayScreenUpdate,
        TileSetUpdate,
        SceneObjectsUpdate,
        QuadTreeGetItems,
        FindPath,
        FindPathEngine
    }
}
